/**
 * 
 */
package galacticthrone.map.mapgen;

import java.util.HashSet;
import java.util.Set;

import galacticthrone.empire.Empire;
import galacticthrone.empire.EmpireColorDefaults;
import galacticthrone.empire.Species;
import galacticthrone.map.MapGenerator;
import galacticthrone.map.data.DataMap;
import galacticthrone.map.data.obs.SolarSystem;
import galacticthrone.map.data.obs.Star;
import galacticthrone.map.namegen.StarNameGen;

/**
 * Generates a map with a uniform density of pure random stars.
 * 
 * @author Jaco van der Westhuizen
 */
public class Uniform implements MapGenerator
{
    private final float bucketSize;
    private final Species playerRace;
    private final int sizeX;
    private final int sizeY;

    private final Set<Empire> empires = new HashSet<Empire>();
    private Empire playerEmpire;

	/**
	 * Constructor.  Initialises the generation parameters.
	 * 
	 * @param sizeX - The east-west size of the map to generate.
	 * @param sizeY - The south-north size of the map to generate.
	 * @param stars - The amount of solar systems to generate.
	 */
	public Uniform(Species playerRace, int sizeX, int sizeY, int stars)
	{
        super();

        this.sizeX = sizeX;
        this.sizeY = sizeY;
        this.bucketSize = (float)Math.sqrt(sizeX * sizeY / stars);
        this.playerRace = playerRace;
	}

    /* (non-Javadoc)
     * @see galacticthrone.map.MapGenerator#generate()
     */
    @Override
    public DataMap generate()
    {
    	DataMap map = new DataMap(sizeX, sizeY);

    	final float midX = sizeX / 2f;
    	final float midY = sizeY / 2f;
    	final float r = Math.min(midX, midY);

        final int bucketsX = (int)(sizeX / bucketSize);
        final int bucketsY = (int)(sizeY / bucketSize);
        
        for (int by = 0; by < bucketsY; by++)
        {
            for (int bx = 0; bx < bucketsX; bx++)
            {
                final int x = (int)((bx + Math.random()) * bucketSize);
                final int y = (int)((by + Math.random()) * bucketSize);
                final float dx = midX - (x + 0.5f);
                final float dy = midY - (y + 0.5f);
                
                if (dx * dx + dy * dy > r * r)
                	continue;

                map.systems.add(createSystem(x, y));
            }
        }
        
        empires.clear();
        
        playerEmpire = new Empire(EmpireColorDefaults.BLUE, playerRace);
        empires.add(playerEmpire);
        
        // TODO Distribute home worlds
        SolarSystem replace = map.systems.get((int)(Math.random() * map.systems.size()));
        map.systems.remove(replace);
        map.systems.add(playerEmpire.makeHomeWorld(map, (int)replace.getPosX(), (int)replace.getPosY()));
        
        return map;
    }
    
    private SolarSystem createSystem(int x, int y)
    {
        return new SolarSystem(x, y, StarNameGen.getNewName(), Star.Color.ALL.get((int)(Math.random() * Star.Color.ALL.size())));
    }

	/* (non-Javadoc)
     * @see galacticthrone.map.MapGenerator#getEmpires()
     */
    @Override
    public Set<Empire> getEmpires()
    {
	    return empires;
    }

	/* (non-Javadoc)
     * @see galacticthrone.map.MapGenerator#getPlayerEmpire()
     */
    @Override
    public Empire getPlayerEmpire()
    {
    	for (Empire empire : empires)
    		return empire;

    	return null;
    }
}
